<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" >

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/turbolinks/5.2.0/turbolinks.js" integrity="sha256-iM4Yzi/zLj/IshPWMC1IluRxTtRjMqjPGd97TZ9yYpU=" crossorigin="anonymous"></script>
  <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Cousine|Inconsolata" rel="stylesheet">
  <link rel="shortcut icon" type="image/png" href="/favicon.png">

  <link rel="stylesheet" href="/css/style.css">
  <link rel="stylesheet" href="/css/css/fontawesome-all.min.css">
  <link rel="stylesheet" href="/css/css/work-sans-v7.css">
  <script src="/js/main.js"></script>

  <!-- Begin Jekyll SEO tag v2.6.1 -->
<title>PY: Vote On Content | Hive Developer</title>
<meta name="generator" content="Jekyll v4.0.0" />
<meta property="og:title" content="PY: Vote On Content" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="How to vote on a post/comment using Python." />
<meta property="og:description" content="How to vote on a post/comment using Python." />
<link rel="canonical" href="vote_on_content.html" />
<meta property="og:url" content="vote_on_content.html" />
<meta property="og:site_name" content="Hive Developer" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2020-08-26T11:52:22-07:00" />
<script type="application/ld+json">
{"description":"How to vote on a post/comment using Python.","mainEntityOfPage":{"@type":"WebPage","@id":"vote_on_content.html"},"@type":"BlogPosting","url":"vote_on_content.html","headline":"PY: Vote On Content","dateModified":"2020-08-26T11:52:22-07:00","datePublished":"2020-08-26T11:52:22-07:00","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->


  
</head>
<body>
<header>
  <h1>
    <button type="button" class="open-nav" id="open-nav"></button>
    <a href="/"  class="logo-link"><img src="/images/logotype_black.svg" height="40" alt="Hive Developer logo"></a>
  </h1>

  
  <form action="/search/" method="get">
    <input type="text" name="q" id="search-input" placeholder="Search">
    <input type="submit" value="Search" style="display: none;">
  </form>
  

  <div id="sidebar" class="sidebar">
	
	
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/">
		<h6 class="ctrl-nav-section title">Introduction</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/#introduction-welcome">Welcome to Hive</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/quickstart/">
		<h6 class="ctrl-nav-section title">Quickstart</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/quickstart/#quickstart-choose-library">Choose Library</a></li>
						
					
						
						<li><a href="/quickstart/#quickstart-hive-full-nodes">Hive Nodes</a></li>
						
					
						
						<li><a href="/quickstart/#quickstart-testnet">Hive Testnet</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/tutorials/">
		<h6 class="ctrl-nav-section title">Tutorials</h6>
		<ul class="cont-nav-section content">
			
				
					
						<li><a href="/tutorials/#tutorials-javascript">Javascript</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-python">Python</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-ruby">Ruby</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-recipes">Recipes</a></li>
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/services/">
		<h6 class="ctrl-nav-section title">Services</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/services/#services-hive-blog">hive.blog</a></li>
						
					
						
						<li><a href="/services/#services-hivesigner">HiveSigner</a></li>
						
					
						
						<li><a href="/services/#services-jussi">Jussi</a></li>
						
					
						
						<li><a href="/services/#services-imagehoster">ImageHoster</a></li>
						
					
						
						<li><a href="/services/#services-dhf">DHF</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/apidefinitions/">
		<h6 class="ctrl-nav-section title">Appbase API</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/apidefinitions/#apidefinitions-condenser-api">Condenser Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-bridge">Bridge</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-account-by-key-api">Account By Key Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-account-history-api">Account History Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-block-api">Block Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-database-api">Database Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-debug-node-api">Debug Node Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-follow-api">Follow Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-jsonrpc">Jsonrpc</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-market-history-api">Market History Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-network-broadcast-api">Network Broadcast Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-rc-api">Rc Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-reputation-api">Reputation Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-rewards-api">Rewards Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-tags-api">Tags Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-transaction-status-api">Transaction Status Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-witness-api">Witness Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-broadcast-ops">Broadcast Ops</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-broadcast-ops-communities">Broadcast Ops Communities</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/resources/">
		<h6 class="ctrl-nav-section title">Resources</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/resources/#resources-overview">Overview</a></li>
						
					
						
						<li><a href="/resources/#resources-client-libs">Client Libraries</a></li>
						
					
						
						<li><a href="/resources/#resources-bluepaper">Bluepaper</a></li>
						
					
						
						<li><a href="/resources/#resources-whitepaper">Whitepaper</a></li>
						
					
						
						<li><a href="/resources/#resources-tools">Tools</a></li>
						
					
						
						<li><a href="/resources/#resources-hivesigner-libs">Hivesigner Libs</a></li>
						
					
						
						<li><a href="/resources/#resources-hive-keychain">Hive Keychain</a></li>
						
					
						
						<li><a href="/resources/#resources-developeradvocate">Community & Help</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/glossary/">
		<h6 class="ctrl-nav-section title">Glossary</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/glossary/#glossary-chain-basics">Chain Basics</a></li>
						
					
						
					
						
						<li><a href="/glossary/#glossary-governance">Governance</a></li>
						
					
						
						<li><a href="/glossary/#glossary-transactions">Transactions</a></li>
						
					
						
						<li><a href="/glossary/#glossary-api">API</a></li>
						
					
						
						<li><a href="/glossary/#glossary-market">Market</a></li>
						
					
				
			
		</ul>
	</section>
	
</div>



  <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
</header>
<div class="main" id="top">
  <div class="hero">
    <h1 class="hero__h1">Hive Developer Portal </h1>
    <img class="hero__img" src="/images/honey-comb-92.png" style="position: relative; top: 10px;" />
  </div>
  <section id="tutorials-python-vote-on-content" class="row tutorials-python-vote-on-content">
	<h3>
		<a id="tutorials-python-vote-on-content">
			PY: Vote On Content
			
		</a>
	</h3>
	
		<span class="description"><p>How to  vote on a post/comment using Python.</p>
</span>
	

	<p><span class="fa-pull-left top-of-tutorial-repo-link"><span class="first-word">Full</span>, runnable src of <a href="https://gitlab.syncad.com/hive/devportal/-/tree/master/tutorials/python/tutorials/17_vote_on_content">Vote On Content</a> can be downloaded as part of: <a href="https://gitlab.syncad.com/hive/devportal/-/tree/master/tutorials/python">tutorials/python</a>.</span>
<br /></p>

<p>In this tutorial we will explain and show you how to to check if a user has voted on specified content and also how to submit a vote on the <strong>Steem</strong> blockchain using the <code class="highlighter-rouge">commit</code> class found within the <a href="https://github.com/steemit/steem-python">steem-python</a> library.</p>

<h2 id="intro">Intro</h2>

<p>Voting is a way of promoting good content via an <code class="highlighter-rouge">upvote</code> or reporting misuse, spam or other unfit content by <code class="highlighter-rouge">downvoting</code>. The Steem python library has a built-in function to transmit transactions to the blockchain. We are using the <code class="highlighter-rouge">vote</code> method found within the <code class="highlighter-rouge">commit</code> class in the the library. Before we vote on content we first check whether the user has already voted. This is not strictly necessary as a voting operation overrides the previous vote value. We use the <code class="highlighter-rouge">get_active_votes</code> function to check for this. This function only requires two parameters, the <code class="highlighter-rouge">author</code> and the <code class="highlighter-rouge">permlink</code> for the comment/post that the query is for. This returns a list of the current voters for that comment. The <code class="highlighter-rouge">vote</code> function has 3 parameters:</p>

<ol>
  <li><em>identifier</em> - This is a combination of the author and permink of the post/comment that the vote will be on</li>
  <li><em>weight</em> - This value determines whether the vote is an upvote (+100.0) or a downvote (-100.0) but this value cannot be 0</li>
  <li><em>username</em> - The name of the account that is executing the vote</li>
</ol>

<h2 id="steps">Steps</h2>

<ol>
  <li><a href="#setup"><strong>App setup</strong></a> - Library install and import. Connection to testnet</li>
  <li><a href="#userinfo"><strong>User information and steem node</strong></a> - Input user information and connection to Steem node</li>
  <li><a href="#votestat"><strong>Check vote status</strong></a> - Vote status of post/comment</li>
  <li><a href="#commit"><strong>Commit vote</strong></a> - Commit vote to the blockchain</li>
</ol>

<h4 id="1-app-setup-">1. App setup <a name="setup"></a></h4>

<p>In this tutorial we use 3 packages:</p>

<ul>
  <li><code class="highlighter-rouge">steem</code> - steem-python library and interaction with Blockchain</li>
  <li><code class="highlighter-rouge">pick</code> - helps select the query type interactively</li>
</ul>

<p>We import the libraries and connect to the <code class="highlighter-rouge">testnet</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">steembase</span>
<span class="kn">import</span> <span class="nn">steem</span>
<span class="kn">from</span> <span class="nn">pick</span> <span class="kn">import</span> <span class="n">pick</span>

<span class="n">steembase</span><span class="o">.</span><span class="n">chains</span><span class="o">.</span><span class="n">known_chains</span><span class="p">[</span><span class="s">'STEEM'</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'chain_id'</span><span class="p">:</span> <span class="s">'79276aea5d4877d9a25892eaa01b0adf019d3e5cb12a97478df3298ccdd01673'</span><span class="p">,</span>
    <span class="s">'prefix'</span><span class="p">:</span> <span class="s">'STX'</span><span class="p">,</span> <span class="s">'steem_symbol'</span><span class="p">:</span> <span class="s">'STEEM'</span><span class="p">,</span> <span class="s">'sbd_symbol'</span><span class="p">:</span> <span class="s">'SBD'</span><span class="p">,</span> <span class="s">'vests_symbol'</span><span class="p">:</span> <span class="s">'VESTS'</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Because this tutorial alters the blockchain we connect to the testnet so we don’t create spam on the production server.</p>

<h4 id="2-user-information-and-steem-node">2. User information and steem node<a name="userinfo"></a></h4>

<p>We also require the <code class="highlighter-rouge">private posting key</code> of the user that wishes to vote on the selected content so the action can be committed to the blockchain. This is why we have to specify this along with the <code class="highlighter-rouge">testnet</code> node. The values are supplied via the terminal/console before we initialise the steem class. We have supplied a test account, <code class="highlighter-rouge">cdemo</code> to use with this tutorial but any account set up on the testnet can be used.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#capture user information
</span><span class="n">username</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Please enter your username: '</span><span class="p">)</span>
<span class="n">postingkey</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Please enter your private posting key: '</span><span class="p">)</span>

<span class="c1">#connect node and private posting key, demo account name: cdemo, posting key: 5JEZ1EiUjFKfsKP32b15Y7jybjvHQPhnvCYZ9BW62H1LDUnMvHz
</span><span class="n">s</span> <span class="o">=</span> <span class="n">steem</span><span class="o">.</span><span class="n">Steem</span><span class="p">(</span><span class="n">nodes</span><span class="o">=</span><span class="p">[</span><span class="s">'https://testnet.steem.vc'</span><span class="p">],</span> <span class="n">keys</span><span class="o">=</span><span class="p">[</span><span class="n">postingkey</span><span class="p">])</span>
</code></pre></div></div>

<h4 id="3-check-vote-status">3. Check vote status<a name="votestat"></a></h4>

<p>In order to give the user an educated choice we first check whether they have already voted on the given post/comment. The author and permlink for the post is supplied via the console/terminal.
If you need to find something to vote on, you can try (https://condenser.steem.vc/) YMMV.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#capture variables
</span><span class="n">author</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Author of post/comment that you wish to vote for: '</span><span class="p">)</span>
<span class="n">permlink</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Permlink of the post/comment you wish to vote for: '</span><span class="p">)</span>
</code></pre></div></div>

<p>The vote status check is done with a simple query to the blockchain.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#check vote status
</span><span class="n">result</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get_active_votes</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="n">permlink</span><span class="p">)</span>
</code></pre></div></div>

<p>This query returns a list of the current voters on the specified post/comment. The result is checked against the username to determine what the current status is.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">result</span><span class="p">:</span>
	<span class="k">for</span> <span class="n">vote</span> <span class="ow">in</span> <span class="n">result</span> <span class="p">:</span>
		<span class="k">if</span> <span class="n">vote</span><span class="p">[</span><span class="s">'voter'</span><span class="p">]</span> <span class="o">==</span> <span class="n">username</span><span class="p">:</span>
			<span class="n">title</span> <span class="o">=</span> <span class="s">"This post/comment has already been voted for"</span>
			<span class="k">break</span>
		<span class="k">else</span><span class="p">:</span>
			<span class="n">title</span> <span class="o">=</span> <span class="s">"No vote for this post/comment has been submitted"</span>
<span class="k">else</span><span class="p">:</span>
	<span class="n">title</span> <span class="o">=</span> <span class="s">"No vote for this post/comment has been submitted"</span>
</code></pre></div></div>

<h4 id="4-commit-vote">4. Commit vote<a name="commit"></a></h4>

<p>The result from the previous step is used to give the user a choice in what the next step in the operation should be.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#option to continue
</span><span class="n">options</span> <span class="o">=</span> <span class="p">[</span><span class="s">'Add/Change vote'</span><span class="p">,</span> <span class="s">'Cancel voting process'</span><span class="p">]</span>
<span class="n">option</span><span class="p">,</span> <span class="n">index</span> <span class="o">=</span> <span class="n">pick</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="n">title</span><span class="p">)</span>
</code></pre></div></div>

<p>The user is given a choice to either continue with the vote or cancel the operation. If the user elects to continue, the <code class="highlighter-rouge">vote</code> function is executed. The weight of the vote is input from the UI and the identifier parameter is created by combining the author and permlink values.</p>

<p><em>It’s important to note that the http client in steem-python will retry <strong>IF</strong> it sends an appbase query and detects a older, non-appbase error</em></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#voting commit
</span><span class="k">if</span> <span class="n">option</span> <span class="o">==</span> <span class="s">'Add/Change vote'</span><span class="p">:</span>
	<span class="n">weight</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="o">+</span><span class="s">'Please advise weight of vote between -100.0 and 100 (not zero): '</span><span class="p">)</span>
	<span class="n">identifier</span> <span class="o">=</span> <span class="p">(</span><span class="s">'@'</span><span class="o">+</span><span class="n">author</span><span class="o">+</span><span class="s">'/'</span><span class="o">+</span><span class="n">permlink</span><span class="p">)</span>
	<span class="k">try</span><span class="p">:</span>
		<span class="k">print</span><span class="p">(</span><span class="s">'Sending vote. ...'</span><span class="p">)</span>
		<span class="n">s</span><span class="o">.</span><span class="n">commit</span><span class="o">.</span><span class="n">vote</span><span class="p">(</span><span class="n">identifier</span><span class="p">,</span> <span class="nb">float</span><span class="p">(</span><span class="n">weight</span><span class="p">),</span> <span class="n">username</span><span class="p">)</span>
		<span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="o">+</span><span class="s">'Vote sent.'</span><span class="p">)</span>
	<span class="k">except</span> <span class="p">(</span><span class="n">RPCErrorRecoverable</span><span class="p">,</span> <span class="n">RPCError</span><span class="p">)</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span> 
		<span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="o">+</span><span class="s">'Exception encountered. Unable to vote'</span><span class="p">)</span>

<span class="k">else</span><span class="p">:</span>
	<span class="k">print</span><span class="p">(</span><span class="s">'Voting has been cancelled'</span><span class="p">)</span>
</code></pre></div></div>

<p>When the function is executed the selected vote weight overrides any value previously recorded on the blockchain.</p>

<p>A simple confirmation of the chosen action is printed on the screen.</p>

<h3 id="to-run-the-tutorial">To Run the tutorial</h3>

<ol>
  <li><a href="getting_started.html">review dev requirements</a></li>
  <li><code class="highlighter-rouge">git clone https://gitlab.syncad.com/hive/devportal.git</code></li>
  <li><code class="highlighter-rouge">cd devportal/tutorials/python/17_vote_on_content</code></li>
  <li><code class="highlighter-rouge">pip install -r requirements.txt</code></li>
  <li><code class="highlighter-rouge">python index.py</code></li>
  <li>After a few moments, you should see a prompt for input in terminal screen.</li>
</ol>

<hr />

</section>

</div>
<div class="footer">
  <a href="#">Back to top</a>
</div>
<script>
    document.getElementById("open-nav").addEventListener("click", function () {
        document.body.classList.toggle("nav-open");
    });
</script>
</body>
</html>


<script src="/js/adjust.js"></script>

